﻿//-----------------------------------------------------------------------
// <copyright file="ViewOperations.cs" company="Redmist">
//     Copyright (c) Damien T Smith. All rights reserved.
// </copyright>
// <author>Damien Smith</author>
//-----------------------------------------------------------------------

namespace Redmist.UsageMonitor.View
{
    using System;
    using System.Drawing;
    using System.IO;
    using System.Windows.Forms;
    using Redmist.UsageMonitor.CustomControls;
    using Redmist.UsageMonitor.Model;

    /// <summary>Contains methods for updating various items in the view.</summary>
    public static class ViewOperations
    {
        /// <summary>Creates a tooltip for the notify icon based on the specified usage model and plan type. </summary>
        /// <param name="model">A Redmist.UsageMonitor.Model.IUsageModel representing the data source for the tooltip.</param>
        /// <param name="planType">A Redmist.UsageMonitor.CustomControls.PlanType representing the type of off peak usage.</param>
        /// <returns>A System.String representing a usage tooltip text.</returns>
        public static string CreateNotifyIconTipText(IUsageModel model, PlanType planType)
        {
            string peakRemainingPercent = ((float)model.PeakRemaining / model.PeakRemainingProgressMaximum * 100).ToString("0");
            string offPeakRemainingPercent = ((float)model.OffPeakRemaining / model.OffPeakRemainingProgressMaximum * 100).ToString("0");
            string timePercentRemaining = ((float)model.BillingSecondsRemaining / model.BillingSecondsMaximum * 100).ToString("0");
            string usageReserve = model.UsageReserve.ToString("N0");
            if (model.UsageReserve >= 0)
            {
                usageReserve = "+" + usageReserve;
            }

            string tipText = string.Empty;
            tipText += string.Format("Peak: {0} MB ({1}%)\n", model.PeakRemaining.ToString("N0"), peakRemainingPercent);
            if (planType == PlanType.UnlimitedOffPeak)
            {
                tipText += "Off Peak: Unlimited\n";
            }
            else
            {
                tipText += string.Format("Off Peak: {0} MB ({1}%)\n", model.OffPeakRemaining.ToString("N0"), offPeakRemainingPercent);
            }

            tipText += string.Format("Days: {0} ({1}%)\n", model.FormattedBillingDaysRemaining, timePercentRemaining);
            tipText += string.Format("Usage vs Days: {0} MB\n", usageReserve);
            tipText += "Last Updated: " + model.LastUpdated.ToString("h:mmtt");
            return tipText;
        }

        /// <summary>Creates an appropriately sized font based on the current system's main (Icon Title) font.</summary>
        /// <param name="formWidth">Thw width of the application form.</param>
        /// <returns>A System.Drawing.Font representing appropriately styled and sized font.</returns>
        /// <remarks>Contains a workaround for Windows XP's (extra) large fonts settings.  Uses a fixed size if the font is too large for the form.</remarks>
        public static Font ResolveApplicationFont(int formWidth)
        {
            Font formFont = new Font(SystemFonts.IconTitleFont, FontStyle.Regular);
            if (formWidth / formFont.GetHeight() < 18)
            {
                formFont = new Font(SystemFonts.IconTitleFont.FontFamily, formWidth / 20, FontStyle.Regular, GraphicsUnit.Pixel);
            }

            return formFont;
        }

        /// <summary>Loads the application icon file.</summary>
        /// <returns>A System.Drawing.Icon representing the application icon.</returns>
        public static Icon RetrieveIconFile()
        {
            return new Icon(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "aaMon.ico"));
        }

        /// <summary>Extracts a large (Windows Vista Icon) PNG image from an Icon derived from an .ico file.</summary>
        /// <param name="icon">A System.Drawing.Icon representing an icon derived from an .ico file containing a large (Vista) icon.</param>
        /// <returns>A System.Drawing.Bitmap reresenting the extracted image.</returns>
        /// <remarks>If no large icon is found, null is returned.</remarks>
        public static Bitmap ExtractLargeIcon(Icon icon)
        {
            Bitmap bmpPngExtracted = null;
            try
            {
                byte[] sourceBuffer = null;
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    icon.Save(memoryStream);
                    sourceBuffer = memoryStream.ToArray();
                }

                int count = BitConverter.ToInt16(sourceBuffer, 4);
                const int IconEntrySize = 6;
                const int IconDirectoryEntrySize = 16;
                for (int i = 0; i < count; i++)
                {
                    int width = sourceBuffer[IconEntrySize + (IconDirectoryEntrySize * i)];
                    int height = sourceBuffer[IconEntrySize + (IconDirectoryEntrySize * i) + 1];
                    int bitCount = BitConverter.ToInt16(sourceBuffer, IconEntrySize + (IconDirectoryEntrySize * i) + 6);
                    if (width == 0 && height == 0 && bitCount == 32)
                    {
                        int imageSize = BitConverter.ToInt32(sourceBuffer, IconEntrySize + (IconDirectoryEntrySize * i) + 8);
                        int imageOffset = BitConverter.ToInt32(sourceBuffer, IconEntrySize + (IconDirectoryEntrySize * i) + 12);
                        MemoryStream destinationStream = new MemoryStream();
                        BinaryWriter binaryWriter = new BinaryWriter(destinationStream);
                        binaryWriter.Write(sourceBuffer, imageOffset, imageSize);
                        destinationStream.Seek(0, SeekOrigin.Begin);
                        bmpPngExtracted = new Bitmap(destinationStream);
                        break;
                    }
                }
            }
            catch
            {
                return null;
            }

            return bmpPngExtracted;
        }
    }
}
